/**
 * @file Threadpool.cc
 * @brief 线程池类的实现
 */

#include "Threadpool.hpp"

#include <unistd.h>

namespace wd
{

// 构造函数：初始化线程池
Threadpool::Threadpool(size_t threadNum, size_t queSize)
: _threadNum(threadNum)
, _taskque(queSize)
, _isExit(false)
{
    //提前开辟好空间
    _threads.reserve(_threadNum);
}

Threadpool::~Threadpool()
{
    if(!_isExit) {
        stop();
    }
}

// 启动线程池：创建并启动所有工作线程
void Threadpool::start()
{
    for(size_t i = 0; i < _threadNum; ++i) {
        unique_ptr<Thread> up(new Thread(
            std::bind(&Threadpool::doTask, this)));
        //unique_ptr<Thread> up(new Thread([=](){
        //    doTask();
        //}));
        //std::move需要显式将一个左值转换为右值
        _threads.push_back(std::move(up));
    }

    for(auto & thread : _threads) {
        thread->start();
    }
}

// 停止线程池：等待任务完成并回收线程
void Threadpool::stop()
{
    printf("Threadpool::stop()\n");
    //当任务队列中还有任务没有执行完毕时，就先等一等
    while(!_taskque.empty()) {
        sleep(2);
    }

    //设置退出标志并唤醒所有线程
    _isExit = true;
    _taskque.wakeup();

    //回收每一个子线程
    for(auto & thread : _threads) {
        thread->join();
    }
}

// 添加任务到队列（生产者角色）
void Threadpool::addTask(Task task)
{
    if(task) {
        _taskque.push(task);
    }
}


// 工作线程执行的任务循环
void Threadpool::doTask()
{
    //不断地从任务队列中取任务
    while(!_isExit) {
        Task task = _taskque.pop();
        if(task) {
            task();
        }
    }
}

}//end of namespace wd
